"""
股票信息模块
"""

import copy

from app.dao import (Base, get_db_session, Column, String, INTEGER, TIMESTAMP, paginate, or_)
from app.common.constants import StockInfoConstants
from app.dto.stockinfo import StockInfoDto
from app.utils.dateutil import get_current_time_str


class StockInfo(Base):
    """
    股票信息类
    """

    # 数据库表名
    __tablename__ = "stock_info"

    # 主键ID
    id = Column('id', INTEGER, primary_key=True, autoincrement=True)
    # 股票代码
    code = Column('code', String(6), nullable=False)
    # 股票名称
    name = Column('name', String(32), nullable=False)
    # 类型
    type = Column('type', INTEGER, nullable=False)
    # 状态
    status = Column('status', INTEGER, nullable=False)
    # 添加时间
    add_time = Column('add_time', TIMESTAMP, nullable=False)
    # 修改时间
    modify_time = Column('modify_time', TIMESTAMP)

    def __str__(self):
        return "({0.id!s}, {0.code!s}, {0.name!s}, {0.type!s}, {0.status!s})".format(self)


class StockInfoDao(object):
    """
    股票信息Dao类
    """

    @classmethod
    def save(cls, item):
        """
        保存
        :param item:
        :return:
        """
        with get_db_session() as session:
            obj = StockInfo(code=item.code, name=item.name, type=item.type, status=item.status,
                            add_time=get_current_time_str())
            session.add(obj)
            session.commit()
            return obj

    @classmethod
    def save_all(cls, item_list):
        """
        批量保存（使用SQLAlchemy Core进行性能优化，只需发送一条SQL）
        :param item_list:
        :return:
        """

        obj_list = []
        for item in item_list:
            obj = StockInfo(code=item.code, name=item.name, type=item.type, status=item.status,
                            add_time=get_current_time_str()).__dict__
            obj_list.append(obj)

        with get_db_session() as session:
            session.execute(StockInfo.__table__.insert(), obj_list)
            session.commit()
        return obj_list

    @classmethod
    def remove_by_id(cls, id_):
        """
        根据id进行逻辑删除
        :param id_:
        :return:
        """
        with get_db_session() as session:
            result = session.query(StockInfo).filter_by(id=id_).update(dict(
                status=StockInfoConstants.Status.DELETE.value[0],
                modify_time=get_current_time_str()
            ))
            session.commit()

        return result

    @classmethod
    def update(cls, item):
        """
        更新
        :param item:
        :return:
        """
        with get_db_session() as session:
            session.commit()
            result = session.query(StockInfo).filter_by(id=item.id).update(dict(
                name=item.name,
                status=item.status,
                modify_time=get_current_time_str()
            ))

        return result

    @classmethod
    def find_by_id(cls, id_):
        """
        根据id获取
        :param id_:
        :return:
        """
        with get_db_session() as session:
            result = session.query(StockInfo).filter_by(id=id_).first()
            if result:
                return copy.deepcopy(result)

    @classmethod
    def find_all(cls):
        """
        获取所有
        :return:
        """

        with get_db_session() as session:
            result = session.query(StockInfo).all()
            if result:
                # 需要使用深度拷贝
                return copy.deepcopy(result)

    @classmethod
    def page_by_param(cls, page=1, page_size=10, **kwargs):
        """
        分页查询
        :param page:
        :param page_size:
        :param kwargs:
        :return:
        """

        if page < 1:
            page = 1

        # 比filter_by的功能更强大，支持比较运算符，支持or、in_等语法。
        filters = set()

        # 模糊查询
        if 'search_item' in kwargs:
            search_item = kwargs['search_item']
            if search_item:
                filters.add(
                    or_(StockInfo.code.ilike('%' + search_item + '%'), StockInfo.name.ilike('%' + search_item + '%')))
        else:
            if 'code' in kwargs:
                code = kwargs['code']
                if code:
                    filters.add(StockInfo.code.ilike('%' + code + '%'))

            if 'name' in kwargs:
                name = kwargs['name']
                if name:
                    filters.add(StockInfo.name.ilike('%' + name + '%'))

        if 'type_' in kwargs:
            type_ = kwargs['type_']
            if type_:
                filters.add(StockInfo.type == kwargs['type_'])

        if 'status' in kwargs:
            status = kwargs['status']
            if status:
                filters.add(StockInfo.status == kwargs['status'])

        with get_db_session() as session:
            page_query = session.query(StockInfo).filter(*filters).order_by(
                StockInfo.status.asc(),
                StockInfo.type.asc(),
                StockInfo.id.desc())
            pagination = paginate(page_query, page=page, page_size=page_size)
            result = dict(
                items=copy.deepcopy(pagination.items),
                previous_page=pagination.previous_page,
                next_page=pagination.next_page,
                has_previous=pagination.has_previous,
                has_next=pagination.has_next,
                total=pagination.total,
                pages=pagination.pages,
                page=page,
            )

            return result


if __name__ == "__main__":
    # code = "00651"
    # name = "格力电器"
    # type_ = StockInfoConstants.Type.SZSE_A.value[0]

    # stock_info = StockInfoDto(code=code, name=name, type_=type_)
    # StockInfoDao.save(stock_info)

    # item_list = StockInfoDao.find_all()
    # for item in item_list:
    #     print(item)

    # status = StockInfoConstants.Status.DELETE.value[0]
    # result = StockInfoDao.page_by_param(type_=type_, name=name, status=status)
    # result = StockInfoDao.page_by_param()
    # print(result)
    # for item in result['items']:
    #     print(item)

    pass
